{
 "metadata": {
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.8-final"
  },
  "orig_nbformat": 2,
  "kernelspec": {
   "name": "python_defaultSpec_1599464698266",
   "display_name": "Python 3.7.8 64-bit ('venv': venv)"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2,
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 第4章开始使用 `PyTorch` 实现深度学习\n",
    "##### 4.1 讲述神经网络和深度学习的历史\n",
    "##### 4.2节说明深度学习实际上在做什么样的计算\n",
    "\n",
    "使用简单模型时深度学习所进行的计算\n",
    "\n",
    "监督学习中使用深度学习分两个阶段：\n",
    "+ 学习阶段\n",
    "\n",
    "    输入和输出使用已知数据，称为`训练数据（学习数据）`\n",
    "\n",
    "    当输入数据被提供给神经网络时，`训练（调整）`网络的连接参数，使得输出尽可能类似于训练数据的正确输出值\n",
    "\n",
    "+ 推理阶段\n",
    "\n",
    "    使用`测试数据`\n",
    "\n",
    "    输入测试数据并获得网络的输出\n",
    "\n",
    "    使用在学习阶段训练获得的连接参数\n",
    "\n",
    "在学习阶段重复一个过程：\n",
    "\n",
    "1. 和推理阶段相同，由输入求得输出。\n",
    "2. 根据`误差函数`求得预期输出与实际输出之间的误差\n",
    "3. 通过`反向传播`求得误差对每个连接参数的`微分`\n",
    "4. 根据每个连接参数的微分值，通过`梯度下降法`更新每个连接参数\n",
    "\n",
    "##### 4.3 使用 `PyTorch` 实现 `MNIST` 手写数字分类任务\n",
    "\n",
    "知名的深度学习框架（库、包）有`Caffe`、`TensorFlow`、`Keras`和`PyTorch`等等\n",
    "\n",
    "`PyTorch`的优点之一是`动态计算图(Define by Run)`，可根据输入数据的大小和维数改变神经网络的形状和计算方法。\n",
    "\n",
    "适合自然语言处理，输入数据维度从一个数据到另一个数据不同的情况特别频繁。\n",
    "\n",
    "`MNIST` 是手写数字的图像数据集，有 60000 个训练数据和 10000 个测试数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 导入数据集，原书使用 fetch_mldata，新版本scikit-learn中已经没有这个包了\n",
    "from sklearn.datasets import fetch_openml\n",
    "mnist = fetch_openml('mnist_784', version=1, cache=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 1.预处理数据\n",
    "x = mnist.data / 255\n",
    "y = mnist.target"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": "标签：5\n"
    },
    {
     "output_type": "display_data",
     "data": {
      "text/plain": "<Figure size 432x288 with 1 Axes>",
      "image/svg+xml": "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\r\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\r\n  \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\r\n<!-- Created with matplotlib (https://matplotlib.org/) -->\r\n<svg height=\"248.518125pt\" version=\"1.1\" viewBox=\"0 0 251.565 248.518125\" width=\"251.565pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\r\n <metadata>\r\n  <rdf:RDF xmlns:cc=\"http://creativecommons.org/ns#\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\r\n   <cc:Work>\r\n    <dc:type rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\"/>\r\n    <dc:date>2020-09-07T16:47:06.495941</dc:date>\r\n    <dc:format>image/svg+xml</dc:format>\r\n    <dc:creator>\r\n     <cc:Agent>\r\n      <dc:title>Matplotlib v3.3.1, https://matplotlib.org/</dc:title>\r\n     </cc:Agent>\r\n    </dc:creator>\r\n   </cc:Work>\r\n  </rdf:RDF>\r\n </metadata>\r\n <defs>\r\n  <style type=\"text/css\">*{stroke-linecap:butt;stroke-linejoin:round;}</style>\r\n </defs>\r\n <g id=\"figure_1\">\r\n  <g id=\"patch_1\">\r\n   <path d=\"M 0 248.518125 \r\nL 251.565 248.518125 \r\nL 251.565 0 \r\nL 0 0 \r\nz\r\n\" style=\"fill:none;\"/>\r\n  </g>\r\n  <g id=\"axes_1\">\r\n   <g id=\"patch_2\">\r\n    <path d=\"M 26.925 224.64 \r\nL 244.365 224.64 \r\nL 244.365 7.2 \r\nL 26.925 7.2 \r\nz\r\n\" style=\"fill:#ffffff;\"/>\r\n   </g>\r\n   <g clip-path=\"url(#p72f779b449)\">\r\n    <image height=\"218\" id=\"image35128a4c2a\" transform=\"scale(1 -1)translate(0 -218)\" width=\"218\" x=\"26.925\" xlink:href=\"data:image/png;base64,\r\n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\" y=\"-6.64\"/>\r\n   </g>\r\n   <g id=\"matplotlib.axis_1\">\r\n    <g id=\"xtick_1\">\r\n     <g id=\"line2d_1\">\r\n      <defs>\r\n       <path d=\"M 0 0 \r\nL 0 3.5 \r\n\" id=\"me3f64d252f\" style=\"stroke:#000000;stroke-width:0.8;\"/>\r\n      </defs>\r\n      <g>\r\n       <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"30.807857\" xlink:href=\"#me3f64d252f\" y=\"224.64\"/>\r\n      </g>\r\n     </g>\r\n     <g id=\"text_1\">\r\n      <!-- 0 -->\r\n      <g transform=\"translate(27.626607 239.238437)scale(0.1 -0.1)\">\r\n       <defs>\r\n        <path d=\"M 31.78125 66.40625 \r\nQ 24.171875 66.40625 20.328125 58.90625 \r\nQ 16.5 51.421875 16.5 36.375 \r\nQ 16.5 21.390625 20.328125 13.890625 \r\nQ 24.171875 6.390625 31.78125 6.390625 \r\nQ 39.453125 6.390625 43.28125 13.890625 \r\nQ 47.125 21.390625 47.125 36.375 \r\nQ 47.125 51.421875 43.28125 58.90625 \r\nQ 39.453125 66.40625 31.78125 66.40625 \r\nz\r\nM 31.78125 74.21875 \r\nQ 44.046875 74.21875 50.515625 64.515625 \r\nQ 56.984375 54.828125 56.984375 36.375 \r\nQ 56.984375 17.96875 50.515625 8.265625 \r\nQ 44.046875 -1.421875 31.78125 -1.421875 \r\nQ 19.53125 -1.421875 13.0625 8.265625 \r\nQ 6.59375 17.96875 6.59375 36.375 \r\nQ 6.59375 54.828125 13.0625 64.515625 \r\nQ 19.53125 74.21875 31.78125 74.21875 \r\nz\r\n\" id=\"DejaVuSans-48\"/>\r\n       </defs>\r\n       <use xlink:href=\"#DejaVuSans-48\"/>\r\n      </g>\r\n     </g>\r\n    </g>\r\n    <g id=\"xtick_2\">\r\n     <g id=\"line2d_2\">\r\n      <g>\r\n       <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"69.636429\" xlink:href=\"#me3f64d252f\" y=\"224.64\"/>\r\n      </g>\r\n     </g>\r\n     <g id=\"text_2\">\r\n      <!-- 5 -->\r\n      <g transform=\"translate(66.455179 239.238437)scale(0.1 -0.1)\">\r\n       <defs>\r\n        <path d=\"M 10.796875 72.90625 \r\nL 49.515625 72.90625 \r\nL 49.515625 64.59375 \r\nL 19.828125 64.59375 \r\nL 19.828125 46.734375 \r\nQ 21.96875 47.46875 24.109375 47.828125 \r\nQ 26.265625 48.1875 28.421875 48.1875 \r\nQ 40.625 48.1875 47.75 41.5 \r\nQ 54.890625 34.8125 54.890625 23.390625 \r\nQ 54.890625 11.625 47.5625 5.09375 \r\nQ 40.234375 -1.421875 26.90625 -1.421875 \r\nQ 22.3125 -1.421875 17.546875 -0.640625 \r\nQ 12.796875 0.140625 7.71875 1.703125 \r\nL 7.71875 11.625 \r\nQ 12.109375 9.234375 16.796875 8.0625 \r\nQ 21.484375 6.890625 26.703125 6.890625 \r\nQ 35.15625 6.890625 40.078125 11.328125 \r\nQ 45.015625 15.765625 45.015625 23.390625 \r\nQ 45.015625 31 40.078125 35.4375 \r\nQ 35.15625 39.890625 26.703125 39.890625 \r\nQ 22.75 39.890625 18.8125 39.015625 \r\nQ 14.890625 38.140625 10.796875 36.28125 \r\nz\r\n\" id=\"DejaVuSans-53\"/>\r\n       </defs>\r\n       <use xlink:href=\"#DejaVuSans-53\"/>\r\n      </g>\r\n     </g>\r\n    </g>\r\n    <g id=\"xtick_3\">\r\n     <g id=\"line2d_3\">\r\n      <g>\r\n       <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"108.465\" xlink:href=\"#me3f64d252f\" y=\"224.64\"/>\r\n      </g>\r\n     </g>\r\n     <g id=\"text_3\">\r\n      <!-- 10 -->\r\n      <g transform=\"translate(102.1025 239.238437)scale(0.1 -0.1)\">\r\n       <defs>\r\n        <path d=\"M 12.40625 8.296875 \r\nL 28.515625 8.296875 \r\nL 28.515625 63.921875 \r\nL 10.984375 60.40625 \r\nL 10.984375 69.390625 \r\nL 28.421875 72.90625 \r\nL 38.28125 72.90625 \r\nL 38.28125 8.296875 \r\nL 54.390625 8.296875 \r\nL 54.390625 0 \r\nL 12.40625 0 \r\nz\r\n\" id=\"DejaVuSans-49\"/>\r\n       </defs>\r\n       <use xlink:href=\"#DejaVuSans-49\"/>\r\n       <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\r\n      </g>\r\n     </g>\r\n    </g>\r\n    <g id=\"xtick_4\">\r\n     <g id=\"line2d_4\">\r\n      <g>\r\n       <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"147.293571\" xlink:href=\"#me3f64d252f\" y=\"224.64\"/>\r\n      </g>\r\n     </g>\r\n     <g id=\"text_4\">\r\n      <!-- 15 -->\r\n      <g transform=\"translate(140.931071 239.238437)scale(0.1 -0.1)\">\r\n       <use xlink:href=\"#DejaVuSans-49\"/>\r\n       <use x=\"63.623047\" xlink:href=\"#DejaVuSans-53\"/>\r\n      </g>\r\n     </g>\r\n    </g>\r\n    <g id=\"xtick_5\">\r\n     <g id=\"line2d_5\">\r\n      <g>\r\n       <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"186.122143\" xlink:href=\"#me3f64d252f\" y=\"224.64\"/>\r\n      </g>\r\n     </g>\r\n     <g id=\"text_5\">\r\n      <!-- 20 -->\r\n      <g transform=\"translate(179.759643 239.238437)scale(0.1 -0.1)\">\r\n       <defs>\r\n        <path d=\"M 19.1875 8.296875 \r\nL 53.609375 8.296875 \r\nL 53.609375 0 \r\nL 7.328125 0 \r\nL 7.328125 8.296875 \r\nQ 12.9375 14.109375 22.625 23.890625 \r\nQ 32.328125 33.6875 34.8125 36.53125 \r\nQ 39.546875 41.84375 41.421875 45.53125 \r\nQ 43.3125 49.21875 43.3125 52.78125 \r\nQ 43.3125 58.59375 39.234375 62.25 \r\nQ 35.15625 65.921875 28.609375 65.921875 \r\nQ 23.96875 65.921875 18.8125 64.3125 \r\nQ 13.671875 62.703125 7.8125 59.421875 \r\nL 7.8125 69.390625 \r\nQ 13.765625 71.78125 18.9375 73 \r\nQ 24.125 74.21875 28.421875 74.21875 \r\nQ 39.75 74.21875 46.484375 68.546875 \r\nQ 53.21875 62.890625 53.21875 53.421875 \r\nQ 53.21875 48.921875 51.53125 44.890625 \r\nQ 49.859375 40.875 45.40625 35.40625 \r\nQ 44.1875 33.984375 37.640625 27.21875 \r\nQ 31.109375 20.453125 19.1875 8.296875 \r\nz\r\n\" id=\"DejaVuSans-50\"/>\r\n       </defs>\r\n       <use xlink:href=\"#DejaVuSans-50\"/>\r\n       <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\r\n      </g>\r\n     </g>\r\n    </g>\r\n    <g id=\"xtick_6\">\r\n     <g id=\"line2d_6\">\r\n      <g>\r\n       <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"224.950714\" xlink:href=\"#me3f64d252f\" y=\"224.64\"/>\r\n      </g>\r\n     </g>\r\n     <g id=\"text_6\">\r\n      <!-- 25 -->\r\n      <g transform=\"translate(218.588214 239.238437)scale(0.1 -0.1)\">\r\n       <use xlink:href=\"#DejaVuSans-50\"/>\r\n       <use x=\"63.623047\" xlink:href=\"#DejaVuSans-53\"/>\r\n      </g>\r\n     </g>\r\n    </g>\r\n   </g>\r\n   <g id=\"matplotlib.axis_2\">\r\n    <g id=\"ytick_1\">\r\n     <g id=\"line2d_7\">\r\n      <defs>\r\n       <path d=\"M 0 0 \r\nL -3.5 0 \r\n\" id=\"ma60ceced64\" style=\"stroke:#000000;stroke-width:0.8;\"/>\r\n      </defs>\r\n      <g>\r\n       <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"26.925\" xlink:href=\"#ma60ceced64\" y=\"11.082857\"/>\r\n      </g>\r\n     </g>\r\n     <g id=\"text_7\">\r\n      <!-- 0 -->\r\n      <g transform=\"translate(13.5625 14.882076)scale(0.1 -0.1)\">\r\n       <use xlink:href=\"#DejaVuSans-48\"/>\r\n      </g>\r\n     </g>\r\n    </g>\r\n    <g id=\"ytick_2\">\r\n     <g id=\"line2d_8\">\r\n      <g>\r\n       <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"26.925\" xlink:href=\"#ma60ceced64\" y=\"49.911429\"/>\r\n      </g>\r\n     </g>\r\n     <g id=\"text_8\">\r\n      <!-- 5 -->\r\n      <g transform=\"translate(13.5625 53.710647)scale(0.1 -0.1)\">\r\n       <use xlink:href=\"#DejaVuSans-53\"/>\r\n      </g>\r\n     </g>\r\n    </g>\r\n    <g id=\"ytick_3\">\r\n     <g id=\"line2d_9\">\r\n      <g>\r\n       <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"26.925\" xlink:href=\"#ma60ceced64\" y=\"88.74\"/>\r\n      </g>\r\n     </g>\r\n     <g id=\"text_9\">\r\n      <!-- 10 -->\r\n      <g transform=\"translate(7.2 92.539219)scale(0.1 -0.1)\">\r\n       <use xlink:href=\"#DejaVuSans-49\"/>\r\n       <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\r\n      </g>\r\n     </g>\r\n    </g>\r\n    <g id=\"ytick_4\">\r\n     <g id=\"line2d_10\">\r\n      <g>\r\n       <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"26.925\" xlink:href=\"#ma60ceced64\" y=\"127.568571\"/>\r\n      </g>\r\n     </g>\r\n     <g id=\"text_10\">\r\n      <!-- 15 -->\r\n      <g transform=\"translate(7.2 131.36779)scale(0.1 -0.1)\">\r\n       <use xlink:href=\"#DejaVuSans-49\"/>\r\n       <use x=\"63.623047\" xlink:href=\"#DejaVuSans-53\"/>\r\n      </g>\r\n     </g>\r\n    </g>\r\n    <g id=\"ytick_5\">\r\n     <g id=\"line2d_11\">\r\n      <g>\r\n       <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"26.925\" xlink:href=\"#ma60ceced64\" y=\"166.397143\"/>\r\n      </g>\r\n     </g>\r\n     <g id=\"text_11\">\r\n      <!-- 20 -->\r\n      <g transform=\"translate(7.2 170.196362)scale(0.1 -0.1)\">\r\n       <use xlink:href=\"#DejaVuSans-50\"/>\r\n       <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\r\n      </g>\r\n     </g>\r\n    </g>\r\n    <g id=\"ytick_6\">\r\n     <g id=\"line2d_12\">\r\n      <g>\r\n       <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"26.925\" xlink:href=\"#ma60ceced64\" y=\"205.225714\"/>\r\n      </g>\r\n     </g>\r\n     <g id=\"text_12\">\r\n      <!-- 25 -->\r\n      <g transform=\"translate(7.2 209.024933)scale(0.1 -0.1)\">\r\n       <use xlink:href=\"#DejaVuSans-50\"/>\r\n       <use x=\"63.623047\" xlink:href=\"#DejaVuSans-53\"/>\r\n      </g>\r\n     </g>\r\n    </g>\r\n   </g>\r\n   <g id=\"patch_3\">\r\n    <path d=\"M 26.925 224.64 \r\nL 26.925 7.2 \r\n\" style=\"fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;\"/>\r\n   </g>\r\n   <g id=\"patch_4\">\r\n    <path d=\"M 244.365 224.64 \r\nL 244.365 7.2 \r\n\" style=\"fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;\"/>\r\n   </g>\r\n   <g id=\"patch_5\">\r\n    <path d=\"M 26.925 224.64 \r\nL 244.365 224.64 \r\n\" style=\"fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;\"/>\r\n   </g>\r\n   <g id=\"patch_6\">\r\n    <path d=\"M 26.925 7.2 \r\nL 244.365 7.2 \r\n\" style=\"fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;\"/>\r\n   </g>\r\n  </g>\r\n </g>\r\n <defs>\r\n  <clipPath id=\"p72f779b449\">\r\n   <rect height=\"217.44\" width=\"217.44\" x=\"26.925\" y=\"7.2\"/>\r\n  </clipPath>\r\n </defs>\r\n</svg>\r\n",
      "image/png": "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\n"
     },
     "metadata": {
      "needs_background": "light"
     }
    }
   ],
   "source": [
    "# 可视化第一个 MNIST 数据\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "\n",
    "plt.imshow(x[0].reshape(28, 28), cmap='gray')\n",
    "print(\"标签：{:}\".format(y[0]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 创建 DataLoader\n",
    "\n",
    "将规范化的 MNIST 数据转换为一个名为 `DataLoader` 的变量\n",
    "\n",
    "该变量可由 `PyTorch` 的神经网络处理\n",
    "\n",
    "1. 分离训练数据和测试数据\n",
    "2. 将 `NumPy` 数据转换为 `Tensor`\n",
    "3. 创建 `Dataset`\n",
    "4. 将 `Dataset` 转换为 `DataLoader`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 2.创建 DataLoader\n",
    "import torch\n",
    "from torch.utils.data import TensorDataset, DataLoader\n",
    "from sklearn.model_selection import train_test_split\n",
    "# 2.1 将数据分成训练和测试（6:1）\n",
    "x_train, x_test, y_train, y_test = train_test_split(\n",
    "    x, y, test_size=1/7, random_state=0)\n",
    "\n",
    "# 2.2 将数据转换为 tensor\n",
    "x_train = torch.Tensor(x_train)\n",
    "x_test = torch.Tensor(x_test)\n",
    "y_train = torch.LongTensor(y_train.astype(float))\n",
    "y_test = torch.LongTensor(y_test.astype(float))\n",
    "\n",
    "# 2.3 使用一组数据和标签创建 Dataset\n",
    "ds_train = TensorDataset(x_train, y_train)\n",
    "ds_test = TensorDataset(x_test, y_test)\n",
    "\n",
    "# 2.4 、使用小批量数据集创建 DataLoader\n",
    "# 与 Chainer 中的 iterators.SerialIterator 类似\n",
    "loader_train = DataLoader(ds_train, batch_size=64, shuffle=True)\n",
    "loader_test = DataLoader(ds_test, batch_size=64, shuffle=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": "Sequential(\n  (fc1): Linear(in_features=784, out_features=100, bias=True)\n  (relu1): ReLU()\n  (fc2): Linear(in_features=100, out_features=100, bias=True)\n  (relu2): ReLU()\n  (fc3): Linear(in_features=100, out_features=10, bias=True)\n)\n"
    }
   ],
   "source": [
    "# 3. 构建网络\n",
    "# Keras 风格\n",
    "# 快速构建，使用 Sequential\n",
    "\n",
    "from torch import nn\n",
    "model = nn.Sequential()\n",
    "model.add_module('fc1', nn.Linear(28*28*1, 100))\n",
    "model.add_module('relu1', nn.ReLU())\n",
    "model.add_module('fc2', nn.Linear(100, 100))\n",
    "model.add_module('relu2', nn.ReLU())\n",
    "model.add_module('fc3', nn.Linear(100, 10))\n",
    "\n",
    "print(model)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 4. 设置误差函数和优化方法\n",
    "from torch import optim\n",
    "# 误差函数，确定实际输出与期望输出之间的误差，这里使用 交叉熵\n",
    "loss_fn = nn.CrossEntropyLoss() # 很多使用使用 criterion 作为变量名\n",
    "\n",
    "# 学习权重参数时的优化方法，Adam 是一种梯度下降法\n",
    "optimizer = optim.Adam(model.parameters(), lr=0.01)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 5. 设置学习和推理\n",
    "# 5.1 定义学习 1 轮所做的事情\n",
    "\n",
    "def train(epoch):\n",
    "    model.train()   # 将网络切换到训练模式\n",
    "\n",
    "    # 从数据加载器中取小批量数据进行计算\n",
    "    for data, targets in loader_train:\n",
    "        optimizer.zero_grad()   # 初始梯度设置为 0\n",
    "        outputs = model(data)   # 输入数据并计算输出\n",
    "        loss = loss_fn(outputs, targets)    # 计算输出和训练数据标签之间的误差\n",
    "        loss.backward() # 对误差进行反向传播\n",
    "        optimizer.step()    #更新权重\n",
    "\n",
    "    print(\"epoch{}：结束\\n\".format(epoch))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 5.2 定义 1 次推理中要做的事情\n",
    "def test():\n",
    "    model.eval()    # 将网络切换到推理模式\n",
    "    correct = 0\n",
    "\n",
    "    # 从数据加载器中取小批量数据进行计算\n",
    "    with torch.no_grad():   # 输入数据并计算输出\n",
    "        for data, targets in loader_test:\n",
    "            outputs = model(data)   # 找到概率最高的标签\n",
    "\n",
    "            # 推论\n",
    "            _, predicted = torch.max(outputs.data, 1)   # 找到概率最高的标签\n",
    "            correct += predicted.eq(targets.data.view_as(predicted)).sum()  # 如果计算结果和标签一致，计数加一\n",
    "\n",
    "    data_num = len(loader_test.dataset) # 数据的总数\n",
    "    print(\"\\n 测试数据的准确率：{}/{}({:.0f}%)\\n\".format(correct, data_num, 100. * correct / data_num))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": "\n 测试数据的准确率：1321/10000(13%)\n\n"
    }
   ],
   "source": [
    "# 未训练时的准确率\n",
    "test()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": "epoch0：结束\n\nepoch1：结束\n\nepoch2：结束\n\n\n 测试数据的准确率：9574/10000(96%)\n\n"
    }
   ],
   "source": [
    "# 6. 执行学习和推理\n",
    "for epoch in range(3):\n",
    "    train(epoch)\n",
    "\n",
    "test()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "通常，除了训练数据之外，\n",
    "+ 还要准备验证数据\n",
    "+ 每轮中检测验证数据和训练数据的误差函数值和准确率\n",
    "+ 每轮还要输出学习进度\n",
    "+ 仅学习适当轮数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": "预测结果是6\n正确标签：6\n"
    },
    {
     "output_type": "display_data",
     "data": {
      "text/plain": "<Figure size 432x288 with 1 Axes>",
      "image/svg+xml": "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\r\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\r\n  \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\r\n<!-- Created with matplotlib (https://matplotlib.org/) -->\r\n<svg height=\"248.518125pt\" version=\"1.1\" viewBox=\"0 0 251.565 248.518125\" width=\"251.565pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\r\n <metadata>\r\n  <rdf:RDF xmlns:cc=\"http://creativecommons.org/ns#\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\r\n   <cc:Work>\r\n    <dc:type rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\"/>\r\n    <dc:date>2020-09-07T16:47:21.479013</dc:date>\r\n    <dc:format>image/svg+xml</dc:format>\r\n    <dc:creator>\r\n     <cc:Agent>\r\n      <dc:title>Matplotlib v3.3.1, https://matplotlib.org/</dc:title>\r\n     </cc:Agent>\r\n    </dc:creator>\r\n   </cc:Work>\r\n  </rdf:RDF>\r\n </metadata>\r\n <defs>\r\n  <style type=\"text/css\">*{stroke-linecap:butt;stroke-linejoin:round;}</style>\r\n </defs>\r\n <g id=\"figure_1\">\r\n  <g id=\"patch_1\">\r\n   <path d=\"M 0 248.518125 \r\nL 251.565 248.518125 \r\nL 251.565 0 \r\nL 0 0 \r\nz\r\n\" style=\"fill:none;\"/>\r\n  </g>\r\n  <g id=\"axes_1\">\r\n   <g id=\"patch_2\">\r\n    <path d=\"M 26.925 224.64 \r\nL 244.365 224.64 \r\nL 244.365 7.2 \r\nL 26.925 7.2 \r\nz\r\n\" style=\"fill:#ffffff;\"/>\r\n   </g>\r\n   <g clip-path=\"url(#pc4fb327ee9)\">\r\n    <image height=\"218\" id=\"image9910ebbb12\" transform=\"scale(1 -1)translate(0 -218)\" width=\"218\" x=\"26.925\" xlink:href=\"data:image/png;base64,\r\niVBORw0KGgoAAAANSUhEUgAAANoAAADaCAYAAADAHVzbAAAFe0lEQVR4nO3dP09UTRjG4YPyEbTE2ElCaaz8VxI7jVZG6Tax00ilxopEqCzs7IzEDtHGQiuNVn4AWVos1RY7eNu3Oc9Elr1Z4LraJxOOkJ+T7GT2THVdt9sBY3XioB8AjgOhQYDQIEBoECA0CBAaBAgNAoQGAUKDAKFBgNAgQGgQIDQIEBoECA0ChAYBQoMAoUGA0CBAaBAgNAgQGgQIDQKEBgFCgwChQYDQIEBoECA0CBAaBAgNAoQGAUKDAKFBgNAgQGgQIDQIEBoECA0ChAYBQoMAoUGA0CBAaBAgNAgQGgQIDQKEBgFCgwChQYDQIEBoECA0CBAaBEwf9AOQd+rUqd7ZmTNnyrW/f/8u51tbW3t6pqPOjgYBQoMAoUGA0CBAaBAgNAjw8X6P06dPl/MbN26U88FgsJ+P80+Gw2E5v3TpUu/s7Nmz5dovX76U83v37pXz1rMdVXY0CBAaBAgNAoQGAUKDAKFBgNAgYKrrut2DfohxePDgQTm/fv16Ob98+XI5392tf21TU1NjWTvu9X///i3Xtq7JtK7ZVD+79dzr6+vl/OnTp+X8IM/w7GgQIDQIEBoECA0ChAYBQoMAoUHAoT5He/LkSe9saWmpXDvus6xnz571zjY3N8u1Gxsb5bx1Blj9Xrqufva5ubly7Z8/f8p56xytevabN2+Wa8+dO1fOt7e3y/m7d+/K+cLCQjkfhR0NAoQGAUKDAKFBgNAgQGgQIDQImOhztPn5+XL+4cOH3tmo52AvXrwo59U5Wde1722NovWdkmtra+W8+re37nQtLy+X83F6/vx5Ob9//345b/3Np6fH9zWndjQIEBoECA0ChAYBQoMAoUHARH+833pFUPX6odbH+3fv3i3nb968KeeT7MePH+W8um7y8+fPcu2dO3fK+bdv38p5ZXV1tZxXf++ua79yamdnp5yfPHmynI/CjgYBQoMAoUGA0CBAaBAgNAgQGgSM717APpidnS3n1bWHra2tcu3Hjx/39EyHwdu3b8v5o0ePemczMzPl2s+fP5fzUa4njXq1qXVO9vXr13I+TnY0CBAaBAgNAoQGAUKDAKFBgNAgYKLP0Vqv2RkMBr2z1pnMUbayslLOq9dGvX79eqSfPcrv/cSJ+v/91jlZ65VSi4uL//xM+8WOBgFCgwChQYDQIEBoECA0CBAaBEz09zq2vkPw1atXvbPWec61a9fK+adPn8r5cdW6I3jlypVy3nrlVKX1XZzjfFXWqOxoECA0CBAaBAgNAoQGAUKDAKFBwESfo50/f76cf//+vXfWOkf79etXOb969Wo5Hw6H5Rz+z44GAUKDAKFBgNAgQGgQIDQImOiP91uqKxdra2vl2tYrgN6/f1/OFxYWyvn29nY553ixo0GA0CBAaBAgNAgQGgQIDQKEBgGH+hytsrS0VM4fP35czlvXbNbX18v5rVu3yjnHix0NAoQGAUKDAKFBgNAgQGgQIDQIOLLnaC2rq6vl/Pbt2+W8dZ9tc3Ozd3bhwoVyrbtsR48dDQKEBgFCgwChQYDQIEBoECA0CDi252gt47zPtrGxUa6dm5sr5xw+djQIEBoECA0ChAYBQoMAoUGA0CDAOdoezc7OlvOXL1/2zi5evFiunZ6e3tMzMbnsaBAgNAgQGgQIDQKEBgFCgwCfI+/RcDgs5w8fPuydDQaD/X4cJpwdDQKEBgFCgwChQYDQIEBoECA0CHBNBgLsaBAgNAgQGgQIDQKEBgFCgwChQYDQIEBoECA0CBAaBAgNAoQGAUKDAKFBgNAgQGgQIDQIEBoECA0ChAYBQoMAoUGA0CBAaBAgNAgQGgQIDQKEBgFCgwChQYDQIEBoECA0CBAaBAgNAoQGAUKDgP8AqfX6rxzTedwAAAAASUVORK5CYII=\" y=\"-6.64\"/>\r\n   </g>\r\n   <g id=\"matplotlib.axis_1\">\r\n    <g id=\"xtick_1\">\r\n     <g id=\"line2d_1\">\r\n      <defs>\r\n       <path d=\"M 0 0 \r\nL 0 3.5 \r\n\" id=\"m6fb7317366\" style=\"stroke:#000000;stroke-width:0.8;\"/>\r\n      </defs>\r\n      <g>\r\n       <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"30.807857\" xlink:href=\"#m6fb7317366\" y=\"224.64\"/>\r\n      </g>\r\n     </g>\r\n     <g id=\"text_1\">\r\n      <!-- 0 -->\r\n      <g transform=\"translate(27.626607 239.238437)scale(0.1 -0.1)\">\r\n       <defs>\r\n        <path d=\"M 31.78125 66.40625 \r\nQ 24.171875 66.40625 20.328125 58.90625 \r\nQ 16.5 51.421875 16.5 36.375 \r\nQ 16.5 21.390625 20.328125 13.890625 \r\nQ 24.171875 6.390625 31.78125 6.390625 \r\nQ 39.453125 6.390625 43.28125 13.890625 \r\nQ 47.125 21.390625 47.125 36.375 \r\nQ 47.125 51.421875 43.28125 58.90625 \r\nQ 39.453125 66.40625 31.78125 66.40625 \r\nz\r\nM 31.78125 74.21875 \r\nQ 44.046875 74.21875 50.515625 64.515625 \r\nQ 56.984375 54.828125 56.984375 36.375 \r\nQ 56.984375 17.96875 50.515625 8.265625 \r\nQ 44.046875 -1.421875 31.78125 -1.421875 \r\nQ 19.53125 -1.421875 13.0625 8.265625 \r\nQ 6.59375 17.96875 6.59375 36.375 \r\nQ 6.59375 54.828125 13.0625 64.515625 \r\nQ 19.53125 74.21875 31.78125 74.21875 \r\nz\r\n\" id=\"DejaVuSans-48\"/>\r\n       </defs>\r\n       <use xlink:href=\"#DejaVuSans-48\"/>\r\n      </g>\r\n     </g>\r\n    </g>\r\n    <g id=\"xtick_2\">\r\n     <g id=\"line2d_2\">\r\n      <g>\r\n       <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"69.636429\" xlink:href=\"#m6fb7317366\" y=\"224.64\"/>\r\n      </g>\r\n     </g>\r\n     <g id=\"text_2\">\r\n      <!-- 5 -->\r\n      <g transform=\"translate(66.455179 239.238437)scale(0.1 -0.1)\">\r\n       <defs>\r\n        <path d=\"M 10.796875 72.90625 \r\nL 49.515625 72.90625 \r\nL 49.515625 64.59375 \r\nL 19.828125 64.59375 \r\nL 19.828125 46.734375 \r\nQ 21.96875 47.46875 24.109375 47.828125 \r\nQ 26.265625 48.1875 28.421875 48.1875 \r\nQ 40.625 48.1875 47.75 41.5 \r\nQ 54.890625 34.8125 54.890625 23.390625 \r\nQ 54.890625 11.625 47.5625 5.09375 \r\nQ 40.234375 -1.421875 26.90625 -1.421875 \r\nQ 22.3125 -1.421875 17.546875 -0.640625 \r\nQ 12.796875 0.140625 7.71875 1.703125 \r\nL 7.71875 11.625 \r\nQ 12.109375 9.234375 16.796875 8.0625 \r\nQ 21.484375 6.890625 26.703125 6.890625 \r\nQ 35.15625 6.890625 40.078125 11.328125 \r\nQ 45.015625 15.765625 45.015625 23.390625 \r\nQ 45.015625 31 40.078125 35.4375 \r\nQ 35.15625 39.890625 26.703125 39.890625 \r\nQ 22.75 39.890625 18.8125 39.015625 \r\nQ 14.890625 38.140625 10.796875 36.28125 \r\nz\r\n\" id=\"DejaVuSans-53\"/>\r\n       </defs>\r\n       <use xlink:href=\"#DejaVuSans-53\"/>\r\n      </g>\r\n     </g>\r\n    </g>\r\n    <g id=\"xtick_3\">\r\n     <g id=\"line2d_3\">\r\n      <g>\r\n       <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"108.465\" xlink:href=\"#m6fb7317366\" y=\"224.64\"/>\r\n      </g>\r\n     </g>\r\n     <g id=\"text_3\">\r\n      <!-- 10 -->\r\n      <g transform=\"translate(102.1025 239.238437)scale(0.1 -0.1)\">\r\n       <defs>\r\n        <path d=\"M 12.40625 8.296875 \r\nL 28.515625 8.296875 \r\nL 28.515625 63.921875 \r\nL 10.984375 60.40625 \r\nL 10.984375 69.390625 \r\nL 28.421875 72.90625 \r\nL 38.28125 72.90625 \r\nL 38.28125 8.296875 \r\nL 54.390625 8.296875 \r\nL 54.390625 0 \r\nL 12.40625 0 \r\nz\r\n\" id=\"DejaVuSans-49\"/>\r\n       </defs>\r\n       <use xlink:href=\"#DejaVuSans-49\"/>\r\n       <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\r\n      </g>\r\n     </g>\r\n    </g>\r\n    <g id=\"xtick_4\">\r\n     <g id=\"line2d_4\">\r\n      <g>\r\n       <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"147.293571\" xlink:href=\"#m6fb7317366\" y=\"224.64\"/>\r\n      </g>\r\n     </g>\r\n     <g id=\"text_4\">\r\n      <!-- 15 -->\r\n      <g transform=\"translate(140.931071 239.238437)scale(0.1 -0.1)\">\r\n       <use xlink:href=\"#DejaVuSans-49\"/>\r\n       <use x=\"63.623047\" xlink:href=\"#DejaVuSans-53\"/>\r\n      </g>\r\n     </g>\r\n    </g>\r\n    <g id=\"xtick_5\">\r\n     <g id=\"line2d_5\">\r\n      <g>\r\n       <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"186.122143\" xlink:href=\"#m6fb7317366\" y=\"224.64\"/>\r\n      </g>\r\n     </g>\r\n     <g id=\"text_5\">\r\n      <!-- 20 -->\r\n      <g transform=\"translate(179.759643 239.238437)scale(0.1 -0.1)\">\r\n       <defs>\r\n        <path d=\"M 19.1875 8.296875 \r\nL 53.609375 8.296875 \r\nL 53.609375 0 \r\nL 7.328125 0 \r\nL 7.328125 8.296875 \r\nQ 12.9375 14.109375 22.625 23.890625 \r\nQ 32.328125 33.6875 34.8125 36.53125 \r\nQ 39.546875 41.84375 41.421875 45.53125 \r\nQ 43.3125 49.21875 43.3125 52.78125 \r\nQ 43.3125 58.59375 39.234375 62.25 \r\nQ 35.15625 65.921875 28.609375 65.921875 \r\nQ 23.96875 65.921875 18.8125 64.3125 \r\nQ 13.671875 62.703125 7.8125 59.421875 \r\nL 7.8125 69.390625 \r\nQ 13.765625 71.78125 18.9375 73 \r\nQ 24.125 74.21875 28.421875 74.21875 \r\nQ 39.75 74.21875 46.484375 68.546875 \r\nQ 53.21875 62.890625 53.21875 53.421875 \r\nQ 53.21875 48.921875 51.53125 44.890625 \r\nQ 49.859375 40.875 45.40625 35.40625 \r\nQ 44.1875 33.984375 37.640625 27.21875 \r\nQ 31.109375 20.453125 19.1875 8.296875 \r\nz\r\n\" id=\"DejaVuSans-50\"/>\r\n       </defs>\r\n       <use xlink:href=\"#DejaVuSans-50\"/>\r\n       <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\r\n      </g>\r\n     </g>\r\n    </g>\r\n    <g id=\"xtick_6\">\r\n     <g id=\"line2d_6\">\r\n      <g>\r\n       <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"224.950714\" xlink:href=\"#m6fb7317366\" y=\"224.64\"/>\r\n      </g>\r\n     </g>\r\n     <g id=\"text_6\">\r\n      <!-- 25 -->\r\n      <g transform=\"translate(218.588214 239.238437)scale(0.1 -0.1)\">\r\n       <use xlink:href=\"#DejaVuSans-50\"/>\r\n       <use x=\"63.623047\" xlink:href=\"#DejaVuSans-53\"/>\r\n      </g>\r\n     </g>\r\n    </g>\r\n   </g>\r\n   <g id=\"matplotlib.axis_2\">\r\n    <g id=\"ytick_1\">\r\n     <g id=\"line2d_7\">\r\n      <defs>\r\n       <path d=\"M 0 0 \r\nL -3.5 0 \r\n\" id=\"ma882cad6a5\" style=\"stroke:#000000;stroke-width:0.8;\"/>\r\n      </defs>\r\n      <g>\r\n       <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"26.925\" xlink:href=\"#ma882cad6a5\" y=\"11.082857\"/>\r\n      </g>\r\n     </g>\r\n     <g id=\"text_7\">\r\n      <!-- 0 -->\r\n      <g transform=\"translate(13.5625 14.882076)scale(0.1 -0.1)\">\r\n       <use xlink:href=\"#DejaVuSans-48\"/>\r\n      </g>\r\n     </g>\r\n    </g>\r\n    <g id=\"ytick_2\">\r\n     <g id=\"line2d_8\">\r\n      <g>\r\n       <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"26.925\" xlink:href=\"#ma882cad6a5\" y=\"49.911429\"/>\r\n      </g>\r\n     </g>\r\n     <g id=\"text_8\">\r\n      <!-- 5 -->\r\n      <g transform=\"translate(13.5625 53.710647)scale(0.1 -0.1)\">\r\n       <use xlink:href=\"#DejaVuSans-53\"/>\r\n      </g>\r\n     </g>\r\n    </g>\r\n    <g id=\"ytick_3\">\r\n     <g id=\"line2d_9\">\r\n      <g>\r\n       <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"26.925\" xlink:href=\"#ma882cad6a5\" y=\"88.74\"/>\r\n      </g>\r\n     </g>\r\n     <g id=\"text_9\">\r\n      <!-- 10 -->\r\n      <g transform=\"translate(7.2 92.539219)scale(0.1 -0.1)\">\r\n       <use xlink:href=\"#DejaVuSans-49\"/>\r\n       <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\r\n      </g>\r\n     </g>\r\n    </g>\r\n    <g id=\"ytick_4\">\r\n     <g id=\"line2d_10\">\r\n      <g>\r\n       <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"26.925\" xlink:href=\"#ma882cad6a5\" y=\"127.568571\"/>\r\n      </g>\r\n     </g>\r\n     <g id=\"text_10\">\r\n      <!-- 15 -->\r\n      <g transform=\"translate(7.2 131.36779)scale(0.1 -0.1)\">\r\n       <use xlink:href=\"#DejaVuSans-49\"/>\r\n       <use x=\"63.623047\" xlink:href=\"#DejaVuSans-53\"/>\r\n      </g>\r\n     </g>\r\n    </g>\r\n    <g id=\"ytick_5\">\r\n     <g id=\"line2d_11\">\r\n      <g>\r\n       <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"26.925\" xlink:href=\"#ma882cad6a5\" y=\"166.397143\"/>\r\n      </g>\r\n     </g>\r\n     <g id=\"text_11\">\r\n      <!-- 20 -->\r\n      <g transform=\"translate(7.2 170.196362)scale(0.1 -0.1)\">\r\n       <use xlink:href=\"#DejaVuSans-50\"/>\r\n       <use x=\"63.623047\" xlink:href=\"#DejaVuSans-48\"/>\r\n      </g>\r\n     </g>\r\n    </g>\r\n    <g id=\"ytick_6\">\r\n     <g id=\"line2d_12\">\r\n      <g>\r\n       <use style=\"stroke:#000000;stroke-width:0.8;\" x=\"26.925\" xlink:href=\"#ma882cad6a5\" y=\"205.225714\"/>\r\n      </g>\r\n     </g>\r\n     <g id=\"text_12\">\r\n      <!-- 25 -->\r\n      <g transform=\"translate(7.2 209.024933)scale(0.1 -0.1)\">\r\n       <use xlink:href=\"#DejaVuSans-50\"/>\r\n       <use x=\"63.623047\" xlink:href=\"#DejaVuSans-53\"/>\r\n      </g>\r\n     </g>\r\n    </g>\r\n   </g>\r\n   <g id=\"patch_3\">\r\n    <path d=\"M 26.925 224.64 \r\nL 26.925 7.2 \r\n\" style=\"fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;\"/>\r\n   </g>\r\n   <g id=\"patch_4\">\r\n    <path d=\"M 244.365 224.64 \r\nL 244.365 7.2 \r\n\" style=\"fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;\"/>\r\n   </g>\r\n   <g id=\"patch_5\">\r\n    <path d=\"M 26.925 224.64 \r\nL 244.365 224.64 \r\n\" style=\"fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;\"/>\r\n   </g>\r\n   <g id=\"patch_6\">\r\n    <path d=\"M 26.925 7.2 \r\nL 244.365 7.2 \r\n\" style=\"fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;\"/>\r\n   </g>\r\n  </g>\r\n </g>\r\n <defs>\r\n  <clipPath id=\"pc4fb327ee9\">\r\n   <rect height=\"217.44\" width=\"217.44\" x=\"26.925\" y=\"7.2\"/>\r\n  </clipPath>\r\n </defs>\r\n</svg>\r\n",
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPsAAAD4CAYAAAAq5pAIAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/d3fzzAAAACXBIWXMAAAsTAAALEwEAmpwYAAANYUlEQVR4nO3db6xU9Z3H8c9HaJ/QPgBxCbGytI0R6yZrFzCbiMpm0/rnCRCNKUZxsxtuSWoCySa7iDE1IdVmd+smPmmkqSkS1qZBsaY2aV3SKD6pAnEV+VNdgyLBi8iD2mDSVb774B6aW7zzO9c5Z+YMfN+v5GZmznfOnG8HPz1nzm/O/BwRAnDhu6jrBgAMB2EHkiDsQBKEHUiCsANJzBzmxmxz6h8YsIjwVMsb7dlt32T7sO03bW9s8loABsv9jrPbniHpd5K+IeldSS9LWh0RBwrrsGcHBmwQe/ZrJL0ZEW9FxB8l/VTSigavB2CAmoT9UklHJz1+t1r2Z2yP2d5je0+DbQFoaOAn6CJii6QtEofxQJea7NmPSbps0uMvVcsAjKAmYX9Z0uW2v2z785K+JemZdtoC0La+D+Mj4mPb90j6laQZkh6LiNdb6wxAq/oeeutrY3xmBwZuIF+qAXD+IOxAEoQdSIKwA0kQdiAJwg4kQdiBJAg7kARhB5Ig7EAShB1IgrADSRB2IAnCDiRB2IEkCDuQBGEHkiDsQBKEHUiCsANJEHYgCcIOJEHYgSQIO5AEYQeSIOxAEoQdSIKwA0kQdiCJvqdsxuhYvHhxz9ratWuL665bt67tdjCiGoXd9hFJH0r6RNLHEbGkjaYAtK+NPfvfRcTJFl4HwADxmR1IomnYQ9Kvbe+1PTbVE2yP2d5je0/DbQFooOlh/LKIOGb7LyQ9Z/tQRLww+QkRsUXSFkmyHQ23B6BPjfbsEXGsuj0haaeka9poCkD7+g677Vm2v3j2vqRvStrfVmMA2uWI/o6sbX9FE3tzaeLjwH9FxPdq1uEwvg+LFi0q1h999NGetWuvvba47syZfNXiQhMRnmp53//SEfGWpL/uuyMAQ8XQG5AEYQeSIOxAEoQdSIKwA0kw7jICNm/eXKxv2rSpWLenHGmRJB08eLCvnnDhYc8OJEHYgSQIO5AEYQeSIOxAEoQdSIKwA0kwzj4E27ZtK9bvuOOOYr3uMuRDhw71rC1durS4LvJgzw4kQdiBJAg7kARhB5Ig7EAShB1IgrADSTDO3oK669HrxtFL16NL0s6dO4v12267rVgHJPbsQBqEHUiCsANJEHYgCcIOJEHYgSQIO5BE31M297Wx83jK5lWrVvWs7dixo7hu3Xv89NNPF+tr1qwp1k+fPl2sI5deUzbX7tltP2b7hO39k5bNsf2c7Teq29ltNgugfdM5jP+JpJvOWbZR0q6IuFzSruoxgBFWG/aIeEHSqXMWr5C0tbq/VdLKdtsC0LZ+vxs/LyKOV/ffkzSv1xNtj0ka63M7AFrS+EKYiIjSibeI2CJpi3R+n6ADznf9Dr2N254vSdXtifZaAjAI/Yb9GUl3V/fvlvTzdtoBMCi14+y2n5C0XNJcSeOSvivpaUk/k7RA0tuSbo+Ic0/iTfVaI3sYv3jx4mL9pZde6lmrux79/fffL9ZvuOGGYr30u/DAuXqNs9d+Zo+I1T1Kf9+oIwBDxddlgSQIO5AEYQeSIOxAEoQdSIKfkq5ceeWVxXqTS4HvuuuuYp2htaktWrSoWL/++uuL9dJlyXXq/s1OnjzZ92t3hT07kARhB5Ig7EAShB1IgrADSRB2IAnCDiTBOHtl2bJlxXrpMtajR48W1923b19fPZ0PZs2aVayXxroff/zx4rrTuPy67/Uvuqi8nxsfHy/WP/jgg2L95ptvLtb37t1brA8Ce3YgCcIOJEHYgSQIO5AEYQeSIOxAEoQdSIIpmyt146oXX3xxz1rdOPvSpUuL9fPx2uizNm/eXKzfe++9PWtNxsmbrj/obe/evbtYX758ebHeRN9TNgO4MBB2IAnCDiRB2IEkCDuQBGEHkiDsQBKMs1eef/75Yr10vXvdmGvdb5Bv3769WB9lBw4cKNavuOKKnrW67yfceeedxfqLL75YrJds27atWK/7fYOFCxcW62fOnCnWZ8yYUaw30fc4u+3HbJ+wvX/SsgdsH7P9SvV3S5vNAmjfdA7jfyLppimW/2dEXF39/bLdtgC0rTbsEfGCpFND6AXAADU5QXeP7Verw/zZvZ5ke8z2Htt7GmwLQEP9hv2Hkr4q6WpJxyX9oNcTI2JLRCyJiCV9bgtAC/oKe0SMR8QnEXFG0o8kXdNuWwDa1lfYbc+f9HCVpP29ngtgNNSOs9t+QtJySXMljUv6bvX4akkh6Yikb0fE8dqNjfA4+4033lisP/vssz1rTa+NfuSRR4r1Bx98sFgf5PXwdXOc79ixo1gv/W+///77i+s+9NBDxfogPfzww8X6+vXri/W6f/OZMwc3ZUOvcfbaLUbE6ikW/7hxRwCGiq/LAkkQdiAJwg4kQdiBJAg7kASXuE7Tfffd17NW93PKg/xJZKk8NHf48OHiugcPHizWV65cWayX3hep3PtVV11VXLduWuQFCxYU66Xeb7311uK6pUtzJen06dPF+s6dO4v1NWvWFOtN8FPSQHKEHUiCsANJEHYgCcIOJEHYgSQIO5AE4+wt2LBhQ7FeN1Z93XXXFetNxukHPcbfZP2PPvqouG7dpbt14+xNpmx+6qmnivW6y3MPHTpUrA8S4+xAcoQdSIKwA0kQdiAJwg4kQdiBJAg7kATj7CPgkksuKdbrfs557dq1bbbzmdSNJ5emPq6b9rhuGu1169YV612OdXeJcXYgOcIOJEHYgSQIO5AEYQeSIOxAEoQdSIJxdgzU3Llze9bqrkevu579nXfe6aunC13f4+y2L7P9G9sHbL9ue321fI7t52y/Ud3ObrtpAO2ZzmH8x5L+OSK+JulvJX3H9tckbZS0KyIul7SregxgRNWGPSKOR8S+6v6Hkg5KulTSCklbq6dtlbRyQD0CaMHMz/Jk2wslfV3SbyXNi4jjVek9SfN6rDMmaaxBjwBaMO2z8ba/IOlJSRsi4veTazFxlm/Kk28RsSUilkTEkkadAmhkWmG3/TlNBH17RJz92c1x2/Or+nxJJwbTIoA21A69eeI3d7dKOhURGyYt/3dJH0TE921vlDQnIv6l5rUYegMGrNfQ23TCvkzSbkmvSTpTLd6kic/tP5O0QNLbkm6PiFM1r0XYgQHrO+xtIuzA4PHjFUByhB1IgrADSRB2IAnCDiRB2IEkCDuQBGEHkiDsQBKEHUiCsANJEHYgCcIOJEHYgSQIO5AEYQeSIOxAEoQdSIKwA0kQdiAJwg4kQdiBJAg7kARhB5Ig7EAShB1IgrADSRB2IAnCDiRRG3bbl9n+je0Dtl+3vb5a/oDtY7Zfqf5uGXy7APo1nfnZ50uaHxH7bH9R0l5JKyXdLukPEfEf094YUzYDA9dryuaZ01jxuKTj1f0PbR+UdGm77QEYtM/0md32Qklfl/TbatE9tl+1/Zjt2T3WGbO9x/aeZq0CaKL2MP5PT7S/IOl5Sd+LiKdsz5N0UlJI2qyJQ/1/rHkNDuOBAet1GD+tsNv+nKRfSPpVRDw8RX2hpF9ExF/VvA5hBwasV9inczbekn4s6eDkoFcn7s5aJWl/0yYBDM50zsYvk7Rb0muSzlSLN0laLelqTRzGH5H07epkXum12LMDA9boML4thB0YvL4P4wFcGAg7kARhB5Ig7EAShB1IgrADSRB2IAnCDiRB2IEkCDuQBGEHkiDsQBKEHUiCsANJ1P7gZMtOSnp70uO51bJRNKq9jWpfEr31q83e/rJXYajXs39q4/aeiFjSWQMFo9rbqPYl0Vu/htUbh/FAEoQdSKLrsG/pePslo9rbqPYl0Vu/htJbp5/ZAQxP13t2AENC2IEkOgm77ZtsH7b9pu2NXfTQi+0jtl+rpqHudH66ag69E7b3T1o2x/Zztt+obqecY6+j3kZiGu/CNOOdvnddT38+9M/stmdI+p2kb0h6V9LLklZHxIGhNtKD7SOSlkRE51/AsH29pD9Ievzs1Fq2/03SqYj4fvV/lLMj4l9HpLcH9Bmn8R5Qb72mGf8HdfjetTn9eT+62LNfI+nNiHgrIv4o6aeSVnTQx8iLiBcknTpn8QpJW6v7WzXxH8vQ9ehtJETE8YjYV93/UNLZacY7fe8KfQ1FF2G/VNLRSY/f1WjN9x6Sfm17r+2xrpuZwrxJ02y9J2lel81MoXYa72E6Z5rxkXnv+pn+vClO0H3asoj4G0k3S/pOdbg6kmLiM9gojZ3+UNJXNTEH4HFJP+iymWqa8SclbYiI30+udfneTdHXUN63LsJ+TNJlkx5/qVo2EiLiWHV7QtJOTXzsGCXjZ2fQrW5PdNzPn0TEeER8EhFnJP1IHb531TTjT0raHhFPVYs7f++m6mtY71sXYX9Z0uW2v2z785K+JemZDvr4FNuzqhMnsj1L0jc1elNRPyPp7ur+3ZJ+3mEvf2ZUpvHuNc24On7vOp/+PCKG/ifpFk2ckf9fSfd10UOPvr4i6X+qv9e77k3SE5o4rPs/TZzb+CdJF0vaJekNSf8tac4I9bZNE1N7v6qJYM3vqLdlmjhEf1XSK9XfLV2/d4W+hvK+8XVZIAlO0AFJEHYgCcIOJEHYgSQIO5AEYQeSIOxAEv8PpI6U8vij4iEAAAAASUVORK5CYII=\n"
     },
     "metadata": {
      "needs_background": "light"
     }
    }
   ],
   "source": [
    "# 推理特定图像数据\n",
    "index = 2020    # 举例，第2020个\n",
    "\n",
    "model.eval()\n",
    "data = x_test[index]\n",
    "output = model(data)\n",
    "_, predicted = torch.max(output.data, 0)\n",
    "print(\"预测结果是{}\".format(predicted))\n",
    "x_text_shouw = (x_test[index]).numpy()\n",
    "plt.imshow(x_text_shouw.reshape(28, 28), cmap='gray')\n",
    "print(\"正确标签：{:}\".format(y_test[index]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": "Net(\n  (fc1): Linear(in_features=784, out_features=100, bias=True)\n  (fc2): Linear(in_features=100, out_features=100, bias=True)\n  (fc3): Linear(in_features=100, out_features=10, bias=True)\n)\n"
    }
   ],
   "source": [
    "# 如果要根据 Chainer 之类的输入实现灵活的计算\n",
    "# 构建更灵活一些的网络\n",
    "\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "class Net(nn.Module):\n",
    "\n",
    "    def __init__(self, n_in, n_mid, n_out):\n",
    "        super(Net, self).__init__()\n",
    "        self.fc1 = nn.Linear(n_in, n_mid)   # 与 Chainer 不同，PyTorch 中 None 不被接受\n",
    "        self.fc2 = nn.Linear(n_mid, n_mid)\n",
    "        self.fc3 = nn.Linear(n_mid, n_out)\n",
    "\n",
    "    def forward(self, x):\n",
    "        # forward 可以改变，以匹配输入 x\n",
    "        h1 = F.relu(self.fc1(x))\n",
    "        h2 = F.relu(self.fc2(h1))\n",
    "        output = self.fc3(h2)\n",
    "        return output\n",
    "\n",
    "model = Net(n_in=28*28*1, n_mid=100, n_out=10)  # 创建网络对象\n",
    "print(model)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ]
}